// Copyright 2007 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package lichen.services;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Collection;

import lichen.hibernate.HibernateModule;
import lichen.hibernate.HibernateSessionFactory;
import lichen.internal.hibernate.HibernateSessionFactoryImpl;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tapestry.internal.services.ClassNameLocatorImpl;
import org.apache.tapestry.ioc.internal.util.CollectionFactory;
import org.apache.tapestry.test.TapestryTestCase;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.transaction.PlatformTransactionManager;

/**
 * @author jcai
 * @version $Revision: 36 $
 * @since 0.0.2
 */
public class ServiceTestCase  extends TapestryTestCase{
	private final Log _log = LogFactory.getLog(ServiceTestCase.class);
	private CglibProxy proxy;
	private Session session;
	private Transaction transaction;
	protected HibernateTemplate hibernateTemplate;
	protected PlatformTransactionManager transactionManager;
	
	protected Session prepareSession() throws Throwable {
		
		
		Collection<String> packageNames = CollectionFactory
				.newList("lichen.entities");

		
		
		HibernateSessionFactory hibernateSource = new HibernateSessionFactoryImpl(_log,
				packageNames, new ClassNameLocatorImpl());
		transactionManager = HibernateModule.buildPlatformTransactionManager(hibernateSource.getSessionFactory());
		
		hibernateTemplate = new HibernateTemplate(hibernateSource.getSessionFactory());
		session = hibernateSource.getSessionFactory().openSession();
		
		session.setFlushMode(FlushMode.COMMIT);
		proxy = new CglibProxy();
		
		return session;
		
	}
	protected   <T> T createProxy(Class<T> clazz,Class[] types,Object[]args) throws Throwable{
		return proxy.createProxy(clazz, types, args);
	}
	protected void newTransaction(){
		transaction = session.beginTransaction();
	}
	protected void commit(){
		session.flush();
		transaction.commit();
	}
	protected void saveOrUpdate(Object obj){
		newTransaction();
		session.saveOrUpdate(obj);
		commit();
	}
	protected <T> T load(Class<T> clazz, Serializable id){
		session.clear();
		return (T) session.load(clazz, id);
	}
	public  class CglibInvocationHandler implements MethodInterceptor {
		public Object intercept(Object o, Method method, Object[] args,
				MethodProxy proxy) throws Throwable {
			System.out.println("------------------------now to execute method ["+method.getName()+"]-----------------------------");
			//方法执行前的操作
			System.out.println("catch before method from cglib proxy");
			boolean isNewTransaction=method.getName().startsWith("save")||method.getName().startsWith("move")||method.getName().startsWith("delete");
			if(isNewTransaction)
				newTransaction();
			Object result = proxy.invokeSuper(o, args); //执行原来类的方法.
			//方法执行后的操作.
			System.out.println("catch after method from cglib proxy");
			if(isNewTransaction){
				commit();
//				session.flush();
			}
			return result;
		}
	}

	public  class CglibProxy {
		public  <T> T createProxy(Class<T> clazz,Class[] types,Object[]args) throws Throwable {
			Enhancer enhancer = new Enhancer();
			CglibInvocationHandler handler=new CglibInvocationHandler();
			enhancer.setSuperclass(clazz);
			enhancer.setCallback(handler);
			return (T) enhancer.create(types,args);
		}
	}
}
